Raspberry Piでパラパラアニメ風の動画を撮影してみる
こんにちはCX事業本部のさかじです。
Raspberry Piで2FPSの動画を作ろうとしてfswebcam
を使用したのですが撮影に時間がかかってしまい2FPSの撮影ができませんでした。画像処理と言ったらOpenCVと思い使ってみました。
環境
- MacBook Pro(macOS Mojave 10.14.6)
- Raspberry Pi 3 Model B+
- webカメラ
- Python 3.5.3
- Open CV 4.1.1
事前準備
$ pip3 --version pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.5) $ pip3 install --upgrade pip $ pip3 --version pip 20.0.2 from /home/pi/.local/lib/python3.5/site-packages/pip (python 3.5) $ sudo apt install libhdf5-dev libhdf5-serial-dev libhdf5-100 $ sudo apt install libqtgui4 libqtwebkit4 libqt4-test python3-pyqt5 $ sudo apt install libatlas-base-dev $ sudo apt install libjasper-dev $ python3 -m pip install opencv-python
通常撮影のプログラム
以下のプログラムでデフォルト設定の撮影ができます。
ソースコード
import cv2 print(cv2.__version__) cap = cv2.VideoCapture(0) print('width :', cap.get(cv2.CAP_PROP_FRAME_WIDTH)) print('height :', cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) print('fps :', cap.get(cv2.CAP_PROP_FPS)) #FPS while (cap.isOpened()): ret, frame = cap.read() cv2.imshow('frame', frame) if cv2.waitKey(1) != -1: break cap.release() cv2.destroyAllWindows()
実行
Raspberry Piのデスクトップで実行すると画面が表示されます。
$ python3 cam.py 4.1.1 width : 640.0 height : 480.0 fps : 30.0
コマ撮りしたい
今回は2fpsの撮影したいので設定を変えてみましょう。
ソースコード(差分のみ)
cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FPS, 2)
実行
$ python3 cam.py 4.1.1 width : 640.0 height : 480.0 fps : 30.0
設定を変えても有効にならないようです。使用しているwebカメラのせいでしょうか?仕方ないので、自分でコマ撮り出来るように作ってみました。
1フレームの処理時間
使用しているカメラは30fpsに対応しているようです。
ret, frame = cap.read()
で次のフレームのが取得できますので処理時間を確認してみます。
ソースコード (差分のみ)
import time
t1 = time.time() * 1000 ret, frame = cap.read() t2 = time.time() * 1000 cv2.imshow('frame', frame) print("diff : {0}[ms], ret : {1}".format((t2 - t1), ret))
実行
$ python3 cam.py 4.1.1 width : 640.0 height : 480.0 fps : 30.0 diff : 564.839111328125[ms], ret : True diff : 11.472900390625[ms], ret : True diff : 13.27197265625[ms], ret : True diff : 11.17578125[ms], ret : True diff : 12.062255859375[ms], ret : True diff : 13.162841796875[ms], ret : True diff : 11.621337890625[ms], ret : True diff : 17.267333984375[ms], ret : True diff : 22.738525390625[ms], ret : True diff : 23.575927734375[ms], ret : True diff : 29.06298828125[ms], ret : True diff : 21.141845703125[ms], ret : True diff : 24.453857421875[ms], ret : True diff : 27.63427734375[ms], ret : True diff : 24.210693359375[ms], ret : True diff : 13.812255859375[ms], ret : True diff : 23.103515625[ms], ret : True
起動直後は時間がかかるようですが、概ね10~30msの間に収まっているようです。このカメラは30FPSということですので33ms以内に描画できればいいので大丈夫そうです。
2PFSで撮影してみる(失敗編)
ソースコード(差分のみ)
while (cap.isOpened()): time.sleep(0.5)
結果
動画が送れるようになりました。単純にsleepするとバッファされている画像が残っているため、再生がもたつくように見えます。
2FPSで撮影してみる
ソースコード(一部)
import math
t = time.time() next_show = math.ceil(t) # 次の0秒から開始 while (cap.isOpened()): t1 = time.time() * 1000 ret, frame = cap.read() t2 = time.time() * 1000 now = time.time() if now >= next_show: cv2.imshow('frame', frame) next_show += 0.5 print('now :', now, 'next :', next_show)
実行結果
now : xxxx next : xxxx
と表示されている時にだけcv2.imshow()
を実施していますので0.5秒ごと(2PFS)は実現できているようです。
pi@ykg-video-dev1:~/tmp/blog $ python3 ./cam.py 4.1.1 width : 640.0 height : 480.0 fps : 30.0 now : 1582965124.5596235 next : 1582965124.5 now : 1582965124.968592 next : 1582965125.0 now : 1582965125.0104537 next : 1582965125.5 now : 1582965125.60014 next : 1582965126.0 now : 1582965126.0907393 next : 1582965126.5
参考サイト
最後に
今回は雑にパラパラ動画を作ってみました。実際動かしてみると処理時間などを意識する必要があり、単純にできないことがわかりました。取得時間を意識はしましたが別のカメラだとうまく行かない可能性もあります。自分が使うカメラの性能を知っておくのも必要ですね。